home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / role / ZorkMachine.lha / zmachine.c < prev    next >
C/C++ Source or Header  |  1992-04-28  |  37KB  |  2,197 lines

  1. /*
  2. *    @(#)zmachine.c    2.24
  3. */
  4.  
  5. # include "zmachine.h"
  6. #ifdef AMIGA
  7. #include <intuition/intuition.h>
  8. #include <dos/dosextens.h>
  9. #include <dos/dostags.h>
  10. #include <exec/memory.h>
  11.  
  12. #include <clib/exec_protos.h>
  13. #include <clib/dos_protos.h>
  14.  
  15. enum    {    ARG_PROTOCOL,ARG_WIDTH,ARG_STORY,ARG_RESTORE,ARG_CUSTOMSCREEN,ARG_COLOUR0,ARG_COLOUR1,ARGCOUNT };
  16.  
  17. extern struct DosLibrary    *DOSBase;
  18. extern UWORD             TwoColours[2];
  19.  
  20. UBYTE                *ProgramName = NULL;
  21. BPTR                 StdOut;
  22.  
  23. #define TRACE
  24.  
  25. #define printf DPrintf
  26.  
  27. #endif
  28.  
  29. #define div foo
  30.  
  31. #include <string.h>
  32. #include <stdlib.h>
  33.  
  34. #undef div
  35.  
  36. #if defined(AMIGA) && defined(AZTEC_C)
  37.  
  38. short            getanyop(int d0);
  39. short            getvarorsp(int d0);
  40. short            getvar(int d0);
  41. void            putvarorsp(int d0, int d1);
  42. void            putsomewhere(int d0);
  43. void            putsomewhereb(int d0);
  44. void            jump(int d1);
  45. unsigned char         *objectp(int d0);
  46. unsigned char         *firstprop(unsigned char *a0);
  47. unsigned char         *nextprop(unsigned char *a0);
  48. void            illegal(void);
  49. void            ret_1(void);
  50. void            ret_0(void);
  51. void            print_im(void);
  52. void            printcr_im(void);
  53. void            nop(void);
  54. void            save_g(void);
  55. int            save_gf(char *p);
  56. void            restore_g(void);
  57. int            restore_gf(char *p);
  58. void            restart_g(void);
  59. void            ret_sp(void);
  60. void            inc_sp(void);
  61. void            halt(void);
  62. void            newline(void);
  63. void            status(void);
  64. void            verify(void);
  65. void            bne(int d0);
  66. void            nextinv(int d0);
  67. void            firstinv(int d0);
  68. void            environment(int d0);
  69. void            l11a7e(int d0);
  70. void            incr(int d0);
  71. void            decr(int d0);
  72. void            print_near(int d0);
  73. void            destructobj(int d1);
  74. void            objshort(int d0);
  75. void            ret(int d0);
  76. void            bra(int d0);
  77. void            print_far(int d0);
  78. void            mov(int d0);
  79. void            not(int d0);
  80. void            sound(int d0,int d1,int d2);
  81. void            bifnotoneof(short *a0);
  82. void            cbge(int d0, int d1);
  83. void            cble(int d0, int d1);
  84. void            dcbge(int d0, int d1);
  85. void            icble(int d0, int d1);
  86. void            bnotcontent(int d0, int d1);
  87. void            bifthen(int d0, int d1);
  88. void            or(int d0, int d1);
  89. void            and(int d0, int d1);
  90. void            tstbit_jz(int d0, int d1);
  91. void            setbit(int d0, int d1);
  92. void            clrbit(int d0, int d1);
  93. void            store(int d0, int d1);
  94. void            moveobj(int d0, int d1);
  95. void            getarrayw(int d0, int d1);
  96. void            getarrayb(int d0, int d1);
  97. void            querypropn(int d0, int d1);
  98. void            getpropnaddr(int d0, int d1);
  99. void            nextpropn(int d0, int d1);
  100. void            add(int d0, int d1);
  101. void            sub(int d0, int d1);
  102. void            mul(int d0, int d1);
  103. void            div(int d0, int d1);
  104. void            mod(int d0, int d1);
  105. void            call(short *a0);
  106. void            putarrayw(int d0, int d1, int d2);
  107. void            putarrayb(int d0, int d1, int d2);
  108. void            setpropn(int d0, int d1, int d2);
  109. unsigned short        findword(unsigned short *a0);
  110. char            *wordend(int c);
  111. void            input(short *a0);
  112. void            print_char(int d0);
  113. void            write_num(int d0);
  114. void            rnd(int d0);
  115. void            push(int d0);
  116. void            pop(int d0);
  117. void            setstatuslen(int d0);
  118. void            gotopos(int d0);
  119. void            run(void);
  120. void            no_mem_error(void);
  121. void            main(int argc, char **argv);
  122.  
  123. #endif
  124.  
  125. char *story_name;
  126. struct dev *printer;
  127.  
  128. jmp_buf restart_buf;
  129.  
  130. /************************************************************************/
  131. int release;
  132. int status_type;
  133.  
  134. UBYTE *ff0;
  135. UBYTE *fec;
  136. char *terms, *my_terms;        /* word terminators        */
  137. UBYTE *first_word, *last_word;
  138. UWORD word_len, word_num;
  139.  
  140. char *line;            /* line buffer during status    */
  141. int use_line = 0;        /* line output            */
  142. UWORD *stack, *framep, *sp;    /* stack management        */
  143.  
  144. #ifdef DEBUG
  145. UWORD ops_ix = 0;
  146. struct {
  147.     UBYTE c_op;
  148.     struct address c_pc;
  149.     UWORD c_sp;
  150.     UWORD c_fp;
  151. } ops[256];
  152. #endif
  153.  
  154. UBYTE *short_cuts;
  155. int save_len;
  156. int status_len;            /* number of status lines    */
  157.  
  158. int line_cnt;
  159.  
  160. int in_status = 1;
  161.  
  162. /************************************************************************/
  163.  
  164. WORD getanyop(d0)
  165. register WORD d0;
  166. {
  167.     WORD getvar();
  168.     WORD op;
  169.  
  170.     if (--d0 < 0) {
  171.         op = fetchw_op();
  172. #ifdef TRACE
  173.         printf("#%04lx.W ",op);
  174. #endif
  175.         return(op);
  176.         }
  177.     else if (d0 == 0) {
  178.         op = fetchb_op();
  179. #ifdef TRACE
  180.         printf("#%02lx.B ",op);
  181. #endif
  182.         return(op);
  183.         }
  184.     else if ((d0 = fetchb_op()) != 0)
  185.         return(getvar(d0));
  186.     else {
  187. #ifdef TRACE
  188.         printf("(SP)+ ");
  189. #endif
  190.         return((WORD)*(sp++));
  191.         }
  192. }
  193.  
  194. WORD getvarorsp(d0)
  195. WORD d0;
  196. {
  197.     WORD getvar();
  198.  
  199.     if (!d0)
  200.         {
  201. #ifdef TRACE
  202.         printf("(SP) ");
  203. #endif
  204.         return((WORD)*sp);
  205.         }
  206.     else
  207.         return(getvar(d0));
  208. }
  209.  
  210. WORD getvar(d0)
  211. WORD d0;
  212. {
  213.     if (d0 < 0x10) {
  214. #ifdef TRACE
  215.         printf("v[%lx] ", d0);
  216. #endif
  217.         return((WORD)framep[- d0 + 1]);
  218.         }
  219.     else {
  220. #ifdef TRACE
  221.         printf("V[%lx] ", d0-0x10);
  222. #endif
  223.         return((WORD)word_get(&fec[(d0 - 0x10)*2]));
  224.         }
  225. }
  226.  
  227. void putvarorsp(d0, d1)
  228. WORD d0, d1;
  229. {
  230.     if (!d0) {
  231. #ifdef TRACE
  232.         printf("->(SP) ");
  233. #endif
  234.         *sp = d1;
  235.         }
  236.     else
  237.         if (d0 < 0x10) {
  238. #ifdef TRACE
  239.             printf("->v[%lx] ", d0);
  240. #endif
  241.             framep[- d0 + 1] = d1;
  242.             }
  243.         else {
  244.             word_put(&fec[(d0 - 0x10)*2], d1);
  245. #ifdef TRACE
  246.             printf("->V[%lx] ", d0-0x10);
  247. #endif
  248.             }
  249. }
  250.  
  251. void putsomewhere(d0)
  252. WORD d0;
  253. {
  254.     WORD d1;
  255.  
  256.     if (d1 = fetchb_op())
  257.         putvarorsp(d1, d0);
  258.     else {
  259. #ifdef TRACE
  260.         printf("->-(SP) ");
  261. #endif
  262.         *(--sp) = d0;
  263.         }
  264. }
  265.  
  266. void putsomewhereb(d0)
  267. WORD d0;
  268. {
  269.     putsomewhere(d0 & 0xff);
  270. }
  271.  
  272. #ifdef DEBUG
  273. void zcore_dump()
  274. {
  275.     int i, ix;
  276.     FILE *fp;
  277.  
  278.     fp = fopen("zcore", "w");
  279.     if (!fp)
  280.         fp = stderr;
  281.  
  282.     fprintf(fp, "sp = %04lx  fp = %04lx\n", sp-stack, framep-stack);
  283.  
  284.     fprintf(fp, "Stack:");
  285.     for (i = 0; i < 256; i++)
  286.     {
  287.         if (!(i % 8))
  288.             fprintf(fp, "\n%04lx: ", i);
  289.  
  290.         fprintf(fp, "%04lx ", stack[i]);
  291.     }
  292.  
  293.     fprintf(fp, "\nLast instructions(fp:sp:addr:op):\n");
  294.     for (i = 256; i; i--)
  295.     {
  296.         ix = (ops_ix++ & 0xff);
  297.         if (!(i % 4))
  298.             fprintf(fp, "\n");
  299.  
  300.         fprintf(fp, "%02lx:%02lx:%05lx:%02lx ", ops[ix].c_fp, ops[ix].c_sp,
  301.         (long)ops[ix].c_pc.offset|((long)ops[ix].c_pc.segment<<9),
  302.         ops[ix].c_op);
  303.     }
  304.     fprintf(fp, "\n");
  305.     unlink("zcore.save");
  306.     save_gf("zcore.save");
  307. }
  308. #endif
  309.  
  310. /************************************************************************/
  311. /*                op-codes                */
  312.  
  313. /************************************************************************/
  314. /*            op-code utilities                */
  315.  
  316. # define dojmp()    jump(0)
  317. # define dontjmp()    jump(1)
  318.  
  319. void jump(d1)
  320. register WORD d1;
  321. {
  322.     register WORD d0;
  323.     void ret_0(), ret_1();
  324.  
  325.     d0 = fetchb_op();
  326.     if(d0 & 0x80)
  327.         d1++;
  328.  
  329.     d0 &= ~0x80;
  330.  
  331.     if (!(d0 & 0x40))
  332.     {
  333.         d0 &= ~0x40;
  334.         d0 <<= 8;
  335.         d0 |= fetchb_op();
  336.         if (d0 & 0x2000)
  337.             d0 |= ~0x3fff;
  338.     }
  339.     else
  340.         d0 &= ~0x40;
  341.  
  342.     if (--d1)
  343.     {
  344.         if (!d0)
  345.             ret_0();
  346.         else if (!(--d0))
  347.             ret_1();
  348.         else
  349.         {
  350.             pc.offset += (d0 - 1);
  351.             load_code();
  352.         }
  353.     }
  354. }
  355.  
  356. UBYTE *objectp(d0)
  357. WORD d0;
  358. {
  359.     return(ff0+9*d0+0x35);
  360. }
  361.  
  362. UBYTE *firstprop(a0)
  363. UBYTE *a0;
  364. {
  365.     register UBYTE *p;
  366.     register WORD d;
  367.  
  368.     p = main_p + word_get(a0+7);
  369.     d = *(p++)*2;
  370.     return(p + d);
  371. }
  372.  
  373. UBYTE *nextprop(a0)
  374. UBYTE *a0;
  375. {
  376.     register WORD d;
  377.  
  378.     d = (*(a0++)>>5) + 1;
  379.     return(a0 + d);
  380. }
  381.  
  382. void illegal()
  383. {
  384. #ifdef DEBUG
  385.     zcore_dump();
  386. #endif
  387.     fatal("Bad operation", story_name);
  388. }
  389.  
  390. /************************************************************************/
  391. /*                class 0                    */
  392.  
  393. void ret_1()
  394. {
  395.     void ret();
  396.     ret(1);
  397. }
  398.  
  399. void ret_0()
  400. {
  401.     void ret();
  402.     ret(0);
  403. }
  404.  
  405. void print_im()
  406. {
  407. #ifdef TRACE
  408.     printf("{\"");
  409.     pdecode(&pc);
  410.     printf("\"} ");
  411. #endif
  412.     decode(&pc);
  413.     load_code();
  414. }
  415.  
  416. void printcr_im()
  417. {
  418.     void newline();
  419.     print_im();
  420.     newline();
  421.     ret_1();
  422. }
  423.  
  424. void nop()
  425. {
  426. }
  427.  
  428. void save_g()
  429. {
  430.     char *name;
  431.     int save_gf();
  432.  
  433.     if (!(name = read_sname()))
  434.         dojmp();
  435.     else
  436.     {
  437. #ifdef AMIGA
  438.         AdjustTitle(FilePart((UBYTE *)name));
  439. #endif    /* AMIGA */
  440.         jump(save_gf(name));
  441.     }
  442. }
  443.  
  444. int save_gf(p)
  445. char *p;
  446. {
  447.     extern char *iovers;
  448.     UWORD *csp;
  449.  
  450.     if (open_save_w(p))
  451.         return(0);
  452.  
  453.     csp = sp;
  454.     *(--sp) = pc.segment;
  455.     *(--sp) = pc.offset;
  456. #ifdef GEMDOS
  457.     /* sorry, its awful but compatibel to infocom's interpreter */
  458.     *(--((long *)sp)) = (UBYTE *)framep - (UBYTE *)stack;
  459.     *(--sp) = release;
  460.     *(((long *)stack)) = (UBYTE *)sp - (UBYTE *)stack;
  461.     *(stack + sizeof(long)/sizeof(UWORD)) = atoi(iovers);
  462. #else
  463.     *(--sp) = framep - stack;
  464.     *(--sp) = release;
  465.     *stack = sp - stack;
  466.     *(stack + 1) = atoi(iovers);
  467. #endif
  468.     sp = csp;
  469.  
  470.     if (write_save(0, 1, stack))
  471.         return(0);
  472.  
  473.     if (write_save(1, save_len, main_p))
  474.         return(0);
  475.  
  476.     if (save_keys())
  477.         return(0);
  478.  
  479.     if (close_save())
  480.         return(0);
  481. #ifdef AMIGA
  482.     saveicon(p);
  483. #endif
  484.     return(1);
  485. }
  486.  
  487. void restore_g()
  488. {
  489.     char *name;
  490.     int restore_gf();
  491.  
  492.     if (!(name = read_rname()))
  493.         dojmp();
  494.     else
  495.     {
  496. #ifdef AMIGA
  497.         AdjustTitle(FilePart((UBYTE *)name));
  498. #endif    /* AMIGA */
  499.         jump(restore_gf(name));
  500.     }
  501. }
  502.  
  503. int restore_gf(p)
  504. char *p;
  505. {
  506.     extern char *iovers;
  507.     int sv;
  508.  
  509.     if (open_save_r(p))
  510.         return(0);
  511.  
  512.     if (read_save(0, 1, stack))
  513.         fatal("Save file read error", p);
  514.  
  515. #ifdef GEMDOS
  516.     sp = (UWORD *)((UBYTE *)stack + *((long *)stack));
  517. #else
  518.     sp = stack + *stack;
  519. #endif
  520.  
  521.     if (*sp++ != release)
  522.         fatal("Wrong save file version", p);
  523.  
  524. #ifdef GEMDOS
  525.     framep = (UBYTE *)stack + *(((long *)sp)++);
  526. #else
  527.     framep = stack + *sp++;
  528. #endif
  529.     pc.offset = *(sp++);
  530.     pc.segment = *(sp++);
  531.  
  532.     sv = word_get(main_h->reserved5);
  533.     if (read_save(1, save_len, main_p))
  534.         fatal("Save file read error", p);
  535.     word_put(main_h->reserved5, sv);
  536.  
  537. #ifdef GEMDOS
  538.     if (*(stack + sizeof(long)/sizeof(UWORD)) == atoi(iovers))
  539. #else
  540.     if (*(stack + 1) == atoi(iovers))
  541. #endif
  542.         if (restore_keys())
  543.             fatal("Save file read error", p);
  544.  
  545.     close_save();
  546.     load_code();
  547.  
  548.     return(1);
  549. }
  550.  
  551. void restart_g()
  552. {
  553.     line_cnt = 0;
  554.     output_chr('\n');
  555.     longjmp(restart_buf,1);
  556. }
  557.  
  558. void ret_sp()
  559. {
  560.     void ret();
  561.     ret(*(sp++));
  562. }
  563.  
  564. void inc_sp()
  565. {
  566.     sp++;
  567. }
  568.  
  569. void halt()
  570. {
  571.     clean_up();
  572.     exit(userexit(0));
  573. }
  574.  
  575. void newline()
  576. {
  577.     output_chr('\n');
  578. }
  579.  
  580. void status()
  581. {
  582.     char    room[256];
  583.     char    *score;
  584.     char    am_pm;
  585.     int    hour;
  586.  
  587.     void    write_num();
  588.     void    objshort();
  589.  
  590.     use_line = 1;
  591.     line = room;
  592.  
  593.     *line++ = ' ';
  594.     objshort(getvarorsp(0x10));
  595.     *(line++) = '\0';
  596.     score = line;
  597.     if (!status_type)
  598.     {
  599.         strcpy(line, "Score: ");
  600.         write_num(getvarorsp(0x11));
  601.         *line++ = '/';
  602.         write_num(getvarorsp(0x12));
  603.     }
  604.     else
  605.     {
  606.         if ((hour = getvarorsp(0x11)) > 12)
  607.         {
  608.             hour -= 12;
  609.             am_pm = 'p';
  610.         }
  611.         else
  612.             am_pm = 'a';
  613.  
  614.         if (hour == 0)
  615.             hour = 12;
  616.  
  617.         strcpy(line, "Time: ");
  618.         line += strlen(line);
  619.         if (hour < 10)
  620.             *line++ = ' ';
  621.         write_num(hour);
  622.         *line++ = ':';
  623.         if (getvarorsp(0x12) < 10)
  624.             *line++ = '0';
  625.         write_num(getvarorsp(0x12));
  626.         *line++ = ' ';
  627.         *line++ = am_pm;
  628.         *line++ = 'm';
  629.     }
  630.     *line++ = ' ';
  631.     *line++ = '\0';
  632.     output_status(room, score);
  633.     use_line = 0;
  634. }
  635.  
  636. void verify()
  637. {
  638.     struct address a, end;
  639.     int m_len;
  640.     long sum;
  641.  
  642.     output_str("Z-Code 3 interpreter V2.24 for ");
  643.     output_str(sysname);
  644.     output_str("\n");
  645.  
  646.     m_len = main_l;
  647.     main_l = 0;
  648.  
  649.     a.segment = 0;
  650.     a.offset = 0x40;
  651.     sum = 0;
  652.     waddr_to_vaddr(&end, word_get(main_h->len));
  653.  
  654.     while(a.segment != end.segment || a.offset != end.offset)
  655.         sum += fetchb_data(&a);
  656.  
  657.     main_l = m_len;
  658.  
  659.     jump((UWORD)sum == word_get(main_h->checksum));
  660. }
  661.  
  662. /************************************************************************/
  663. /*                class 1                    */
  664.  
  665. /* for tracing purpose: pdecode prints a decoded string to stdout */
  666.  
  667. #ifdef TRACE
  668. void pobjshort(d0)
  669. WORD d0;
  670. {
  671.     struct address a;
  672.  
  673.     if (d0) {
  674.         baddr_to_vaddr(&a, word_get(objectp(d0)+7) + 1);
  675.         pdecode(&a);
  676.         }
  677.     else
  678.         printf("NULL");
  679. }
  680. #endif
  681.  
  682. void bne(d0)
  683. WORD d0;
  684. {
  685. #ifdef TRACE
  686.     printf("{%lx} ",d0);
  687. #endif
  688.     if(d0)
  689.         dojmp();
  690.     else
  691.         dontjmp();
  692. }
  693.  
  694. void nextinv(d0)
  695. WORD d0;
  696. {
  697.     register UBYTE d1;
  698.  
  699. #ifdef TRACE
  700.     printf("{OBJ(");
  701.     pobjshort(d0);
  702.     printf(")->OBJ(");
  703.     pobjshort(objectp(d0)[5]);
  704.     printf(")} ");
  705. #endif
  706.     putsomewhere(d1 = objectp(d0)[5]);
  707.  
  708.     if (d1)
  709.         dontjmp();
  710.     else
  711.         dojmp();
  712. }
  713.  
  714. void firstinv(d0)
  715. WORD d0;
  716. {
  717.     register UBYTE d1;
  718.  
  719. #ifdef TRACE
  720.     printf("{OBJ(");
  721.     pobjshort(d0);
  722.     printf(")->OBJ(");
  723.     pobjshort(objectp(d0)[6]);
  724.     printf(")} ");
  725. #endif
  726.     putsomewhere(d1 = objectp(d0)[6]);
  727.  
  728.     if (d1)
  729.         dontjmp();
  730.     else
  731.         dojmp();
  732. }
  733.  
  734. void environment(d0)
  735. WORD d0;
  736. {
  737. #ifdef TRACE
  738.     printf("{OBJ(");
  739.     pobjshort(d0);
  740.     printf(")->OBJ(");
  741.     pobjshort(objectp(d0)[4]);
  742.     printf(")} ");
  743. #endif TRACE
  744.     putsomewhere(objectp(d0)[4]);
  745. }
  746.  
  747. void l11a7e(d0)
  748. WORD d0;
  749. {
  750.     putsomewhere((main_p[d0-1]>>5)+1);
  751. }
  752.  
  753. void incr(d0)
  754. WORD d0;
  755. {
  756.     putvarorsp(d0,getvarorsp(d0)+1);
  757. }
  758.  
  759. void decr(d0)
  760. WORD d0;
  761. {
  762.     putvarorsp(d0,getvarorsp(d0)-1);
  763. }
  764.  
  765. void print_near(d0)
  766. WORD d0;
  767. {
  768.     struct address a;
  769.     baddr_to_vaddr(&a,d0);
  770.     decode(&a);
  771. }
  772.  
  773. void destructobj(d1)
  774. WORD d1;
  775. {
  776.     register UBYTE *a0, *a1;
  777.     register UWORD d0;
  778.  
  779. #ifdef TRACE
  780.     printf("{OBJ(");
  781.     pobjshort(d1);
  782.     printf(")} ");
  783. #endif
  784.  
  785.     a1 = objectp(d1);
  786.     if (d0 = a1[4])
  787.     {
  788.         d0 = (a0 = objectp(d0))[6];
  789.         if (d1 == d0)
  790.             a0[6] = a1[5];
  791.         else
  792.         {
  793.             while ((d0 = (a0 = objectp(d0))[5]) != d1)
  794.                 ;
  795.             a0[5] = a1[5];
  796.         }
  797.         a1[4] = a1[5] = 0;
  798.     }
  799. }
  800.  
  801. void objshort(d0)
  802. WORD d0;
  803. {
  804.     struct address a;
  805.  
  806. #ifdef TRACE
  807.     printf("{OBJ(");
  808.     pobjshort(d0);
  809.     printf(")} ");
  810. #endif
  811.  
  812.     baddr_to_vaddr(&a, word_get(objectp(d0)+7) + 1);
  813.     decode(&a);
  814. }
  815.  
  816. void ret(d0)
  817. WORD d0;
  818. {
  819.     sp = framep + 1;
  820. #ifdef GEMDOS
  821.     framep = (UBYTE *)stack + *(((long *)sp)++);
  822. #else
  823.     framep = stack + *sp++;
  824. #endif
  825.     pc.offset = *(sp++);
  826.     pc.segment = *(sp++);
  827.     load_code();
  828.     putsomewhere(d0);
  829. }
  830.  
  831. void bra(d0)
  832. WORD d0;
  833. {
  834.     pc.offset += (d0 - 2);
  835.     load_code();
  836. }
  837.  
  838. void print_far(d0)
  839. WORD d0;
  840. {
  841.     struct address a;
  842.     waddr_to_vaddr(&a, d0);
  843.     decode(&a);
  844. }
  845.  
  846. void mov(d0)
  847. WORD d0;
  848. {
  849.     putsomewhere(getvarorsp(d0));
  850. }
  851.  
  852. void not(d0)
  853. WORD d0;
  854. {
  855.     putsomewhere(~d0);
  856. }
  857.  
  858. /************************************************************************/
  859. /*                class 2                    */
  860.  
  861. void
  862. sound(d0,d1,d2)
  863. int d0,d1,d2;
  864. {
  865.     PlaySound(d0,d2);
  866.  
  867.     /* d0 -> Soundnummer */
  868.     /* d1 -> Flags? */
  869.     /* d2 -> Lautstärke (0 .. 8) */
  870. }
  871.  
  872. void bifnotoneof(a0)
  873. register WORD *a0;
  874. {
  875.     register WORD d0, d1;
  876.  
  877.     d1 = *(a0++) - 1;
  878.     d0 = *(a0++);
  879.  
  880.     for(;;)
  881.         if(*(a0++) == d0)
  882.         {
  883.             dontjmp();
  884.             break;
  885.         }
  886.         else if (!--d1)
  887.         {
  888.             dojmp();
  889.             break;
  890.         }
  891. }
  892.  
  893. void cbge(d0, d1)
  894. WORD d0, d1;
  895. {
  896.     jump(d0 < d1);
  897. }
  898.  
  899. void cble(d0, d1)
  900. WORD d0, d1;
  901. {
  902.     jump(d0 > d1);
  903. }
  904.  
  905. void dcbge(d0, d1)        /* decrement, compare and jump greater equal */
  906. WORD d0, d1;            /* dcbge */
  907. {
  908.     register WORD d2;
  909.  
  910.     d2 = getvarorsp(d0) - 1;
  911.     putvarorsp(d0,d2);
  912.     if (d2 < d1)
  913.         dontjmp();
  914.     else
  915.         dojmp();
  916. }
  917.  
  918. void icble(d0, d1)        /* increment, compare and jump less equal */
  919. WORD d0, d1;            /* icble */
  920. {
  921.     register WORD d2;
  922.  
  923.     d2 = getvarorsp(d0) + 1;
  924.     putvarorsp(d0,d2);
  925.     if (d2 > d1)
  926.         dontjmp();
  927.     else
  928.         dojmp();
  929. }
  930.  
  931. void bnotcontent(d0, d1)    /* branch if d0 is not contained in d1 */
  932. WORD d0, d1;
  933. {
  934. #ifdef TRACE
  935.     printf("{OBJ(");
  936.     pobjshort(d0);
  937.     printf(")<OBJ(");
  938.     pobjshort(d1);
  939.     printf(")?->%lx} ",objectp(d0)[4]==d1);
  940. #endif
  941.  
  942.     if (objectp(d0)[4] == d1)
  943.         dontjmp();
  944.     else
  945.         dojmp();
  946. }
  947.  
  948. void bifthen(d0, d1)
  949. WORD d0, d1;
  950. {
  951.     jump((d1 & ~d0) == 0);
  952. }
  953.  
  954. void or(d0, d1)
  955. WORD d0, d1;
  956. {
  957.     putsomewhere(d0 | d1);
  958. }
  959.  
  960. void and(d0, d1)
  961. {
  962.     putsomewhere(d0 & d1);
  963. }
  964.  
  965. #define tst(a0, d0)    (a0[d0 >> 3] & (1<<((~d0)&7)))
  966. #define clr(a0, d0)    (a0[d0 >> 3] &= ~(1<<((~d0)&7)))
  967. #define set(a0, d0)    (a0[d0 >> 3] |= (1<<((~d0)&7)))
  968. /* these are bits in an object */
  969.  
  970. void tstbit_jz(d0, d1)
  971. WORD d0, d1;
  972. {
  973. #ifdef TRACE
  974.     printf("{OBJ(");
  975.     pobjshort(d0);
  976.     printf(").%lx->%lx} ",d1,tst(objectp(d0), d1));
  977. #endif
  978.  
  979.     if (tst(objectp(d0), d1))
  980.         dontjmp();
  981.     else
  982.         dojmp();
  983. }
  984.  
  985. void setbit(d0, d1)
  986. WORD d0, d1;
  987. {
  988. #ifdef TRACE
  989.     printf("{OBJ(");
  990.     pobjshort(d0);
  991.     printf(").%lx=1} ",d1);
  992. #endif
  993.  
  994.     set(objectp(d0), d1);
  995. }
  996.  
  997. void clrbit(d0, d1)
  998. WORD d0, d1;
  999. {
  1000. #ifdef TRACE
  1001.     printf("{OBJ(");
  1002.     pobjshort(d0);
  1003.     printf(").%lx=0} ",d1);
  1004. #endif
  1005.  
  1006.     clr(objectp(d0), d1);
  1007. }
  1008.  
  1009. void store(d0, d1)
  1010. WORD d0, d1;
  1011. {
  1012.     putvarorsp(d0, d1);
  1013. }
  1014.  
  1015. void moveobj(d0, d1)
  1016. WORD d0, d1;
  1017. {
  1018.     register UBYTE *a0, *a1;
  1019.     void destructobj();
  1020.  
  1021. #ifdef TRACE
  1022.     printf("{OBJ(");
  1023.     pobjshort(d0);
  1024.     printf(")->OBJ(");
  1025.     pobjshort(d1);
  1026.     printf(")} ");
  1027. #endif
  1028.  
  1029.     destructobj(d0);
  1030.     a1 = objectp(d1);
  1031.     a0 = objectp(d0);
  1032.  
  1033.     a0[5] = a1[6];
  1034.     a0[4] = d1;
  1035.     a1[6] = d0;
  1036. }
  1037.  
  1038. void getarrayw(d0, d1)
  1039. WORD d0, d1;
  1040. {
  1041.     struct address a;
  1042.     baddr_to_vaddr(&a, d0 + d1 * 2);
  1043.     putsomewhere(fetchw_data(&a));
  1044. }
  1045.  
  1046. void getarrayb(d0, d1)
  1047. WORD d0, d1;
  1048. {
  1049.     struct address a;
  1050.     baddr_to_vaddr(&a, d0 + d1);
  1051.     putsomewhereb(fetchb_data(&a));
  1052. }
  1053.  
  1054. void querypropn(d0, d1)
  1055. register WORD d0, d1;
  1056. {
  1057.     register UBYTE *a0;
  1058.  
  1059. #ifdef TRACE
  1060.     printf("{OBJ(");
  1061.     pobjshort(d0);
  1062.     printf(")::%lx->",d1);
  1063. #endif
  1064.  
  1065.     for (a0 = firstprop(objectp(d0)); d1 < (d0 = *a0 & 0x1f); a0 = nextprop(a0))
  1066.         ;
  1067.  
  1068.     if (d1 == d0)
  1069.     {
  1070.         if (!(*(a0++) & 0x20)) {
  1071. #ifdef TRACE
  1072.             printf("%02lx.B} ",*a0);
  1073. #endif
  1074.             putsomewhereb(*a0);
  1075.             }
  1076.         else {
  1077. #ifdef TRACE
  1078.             printf("%04lx.W} ",word_get(a0));
  1079. #endif
  1080.             putsomewhere(word_get(a0));
  1081.             }
  1082.     }
  1083.     else
  1084.         {
  1085. #ifdef TRACE
  1086.         printf("%04lx.I} ",word_get(&ff0[(d1-1) * 2]));
  1087. #endif
  1088.         putsomewhere(word_get(&ff0[(d1-1) * 2]));
  1089.         }
  1090.  
  1091. }
  1092.  
  1093. void getpropnaddr(d0, d1)
  1094. register WORD d0, d1;
  1095. {
  1096.     register UBYTE *a0;
  1097.  
  1098. #ifdef TRACE
  1099.     printf("{OBJ(");
  1100.     pobjshort(d0);
  1101.     printf(")::%lx}",d1);
  1102. #endif
  1103.  
  1104.     for (a0 = firstprop(objectp(d0)); d1 < (d0 = *a0 & 0x1f); a0 = nextprop(a0))
  1105.         ;
  1106.  
  1107.     if (d1 != d0)
  1108.         putsomewhere(0);
  1109.     else
  1110.         putsomewhere(++a0 - main_p);
  1111. }
  1112.  
  1113. void nextpropn(d0, d1)
  1114. register WORD d0, d1;
  1115. {
  1116.     register UBYTE *a0;
  1117.  
  1118. #ifdef TRACE
  1119.     printf("{OBJ(");
  1120.     pobjshort(d0);
  1121.     printf(")::%lx}",d1);
  1122. #endif
  1123.  
  1124.     a0 = firstprop(objectp(d0));
  1125.  
  1126.     if (d1)
  1127.     {
  1128.         for(;  d1 < (d0 = *a0 & 0x1f); a0 = nextprop(a0))
  1129.             ;
  1130.         if (d1 != d0)
  1131.             fatal("Non-existant next property", story_name);
  1132.         else
  1133.             a0 = nextprop(a0);
  1134.     }
  1135.     putsomewhere(*a0 & 0x1f);
  1136. }
  1137.  
  1138. void add(d0, d1)
  1139. WORD d0, d1;
  1140. {
  1141.     putsomewhere(d0 + d1);
  1142. }
  1143.  
  1144. void sub(d0, d1)
  1145. WORD d0, d1;
  1146. {
  1147.     putsomewhere(d0 - d1);
  1148. }
  1149.  
  1150. void mul(d0, d1)
  1151. WORD d0, d1;
  1152. {
  1153.     putsomewhere(d0 * d1);
  1154. }
  1155.  
  1156. void div(d0, d1)
  1157. WORD d0, d1;
  1158. {
  1159.     putsomewhere(d0 / d1);
  1160. }
  1161.  
  1162. void mod(d0, d1)
  1163. WORD d0, d1;
  1164. {
  1165.     putsomewhere(d0 % d1);
  1166. }
  1167.  
  1168. void call(a0)
  1169. register WORD *a0;
  1170. {
  1171.     register WORD d0, d1, d2;
  1172.  
  1173.     d2 = *(a0++);
  1174.     if ((d0 = *(a0++)) == 0)
  1175.         putsomewhere(0);
  1176.     else
  1177.     {
  1178.         d2--;
  1179.         *(--sp) = pc.segment;
  1180.         *(--sp) = pc.offset;
  1181. #ifdef GEMDOS
  1182.         *(--((long *)sp)) = (UBYTE *)framep - (UBYTE *)stack;
  1183. #else
  1184.         *(--sp) = framep - stack;
  1185. #endif
  1186.         waddr_to_vaddr(&pc,d0);
  1187.         load_code();
  1188.         framep = sp - 1;
  1189.         if (d1 = fetchb_op())
  1190.         {
  1191.             do
  1192.             {
  1193.                 d0 = fetchw_op();
  1194.                 if (--d2 >= 0)
  1195.                     d0 = *(a0++);
  1196.                 *(--sp) = d0;
  1197.             }
  1198.             while (--d1 > 0);
  1199.         }
  1200.     }
  1201. }
  1202.  
  1203. void putarrayw(d0, d1, d2)
  1204. WORD d0, d1, d2;
  1205. {
  1206.     word_put(&main_p[d0 + d1 * 2], d2);
  1207. }
  1208.  
  1209.  
  1210. void putarrayb(d0, d1, d2)
  1211. WORD d0, d1; WORD d2;
  1212. {
  1213.     main_p[d0+d1] = (UBYTE)d2;
  1214. }
  1215.  
  1216. void setpropn(d0, d1, d2)
  1217. register WORD d0, d1; WORD d2;
  1218. {
  1219.     register UBYTE *a0;
  1220.  
  1221. #ifdef TRACE
  1222.     printf("{OBJ(");
  1223.     pobjshort(d0);
  1224.     printf(")::%lx=",d1);
  1225. #endif
  1226.  
  1227.     for (a0 = firstprop(objectp(d0)); d1 < (d0 = *a0 & 0x1f); a0 = nextprop(a0))
  1228.         ;
  1229.  
  1230.     if (d1 != d0)
  1231.         fatal("Non-existant put property", story_name);
  1232.  
  1233.     if (*(a0++) & 0x20) {
  1234. #ifdef TRACE
  1235.         printf("%04lx.W} ",d2);
  1236. #endif
  1237.         word_put(a0, d2);
  1238.         }
  1239.     else {
  1240. #ifdef TRACE
  1241.         printf("%02lx.B} ",d2);
  1242. #endif
  1243.         *a0 = d2;
  1244.         }
  1245. }
  1246.  
  1247. UWORD findword(a0)
  1248. UWORD *a0;
  1249. {
  1250.     register UWORD d0, step, code0, code1;
  1251.     register UBYTE *word;
  1252.  
  1253.     d0 = word_num;
  1254.     step = word_len;
  1255.  
  1256.     code0 = *a0;
  1257.     code1 = *(a0+1);
  1258.  
  1259.     for ( d0 >>= 1, step <<= 1; d0 >>= 1; step <<= 1)
  1260.         ;
  1261.  
  1262.     word = &first_word[step - word_len];
  1263.  
  1264.     do
  1265.     {
  1266.         step >>= 1;
  1267.         d0 = word_get(word);
  1268.         if (code0 <= d0)
  1269.         {
  1270.             if (code0 != d0)
  1271.                 word -= step;
  1272.             else
  1273.             {
  1274.                 d0 = word_get(word+2);
  1275.                 if (code1 <= d0)
  1276.                 {
  1277.                     if (code1 != d0)
  1278.                         word -= step;
  1279.                     else
  1280.                         return(word - main_p);
  1281.                 }
  1282.                 else
  1283.                 {
  1284.                     word += step;
  1285.                     if (last_word < word)
  1286.                         word = last_word;
  1287.                 }
  1288.             }
  1289.         }
  1290.         else
  1291.         {
  1292.             word += step;
  1293.             if (last_word < word)
  1294.                 word = last_word;
  1295.         }
  1296.     }
  1297.     while(word_len <= step);
  1298.     return(0);
  1299. }
  1300.  
  1301. char *wordend(c)
  1302. register char c;
  1303. {
  1304.     register char *p;
  1305.  
  1306.     for(p = terms; *p; p++)
  1307.         if (*p == c)
  1308.             return (p);
  1309.     return(NULL);
  1310. }
  1311.  
  1312. void no_mem_error()
  1313. {
  1314.     fatal("Out of memory", NULL);
  1315. }
  1316.  
  1317. void input(a0)
  1318. WORD *a0;
  1319. {
  1320.     char c;
  1321.     char *inp;        /* input field                */
  1322.     char *end;        /* end of input line            */
  1323.     UBYTE *out;        /* output field                */
  1324.     UBYTE *outp;        /* pointer into output field        */
  1325.     char src_word[8];    /* source word                */
  1326.     UWORD dst_word[4];    /* word coded in z-code            */
  1327.     register char *lp;    /* pointer into line            */
  1328.     register char *cp;    /* pointer into src_word        */
  1329.     char *ws;        /* pointer into line (start of line)    */
  1330.     register int wc;    /* word count                */
  1331.     register char *p;    /* scratch                */
  1332.     static struct hist_buf history = {I_HIST_LEN, NULL, NULL};
  1333.                 /* history buffer            */
  1334.  
  1335.     if (!history.hb)
  1336.     {
  1337.         if (!(history.undo = history.hb = (char *)malloc(history.len)))
  1338.             no_mem_error();
  1339.         else
  1340.             history.hb[0] = history.hb[1] = '\0';
  1341.     }
  1342.  
  1343.     inp = (char *)&main_p[a0[1]];
  1344.     out = &main_p[a0[2]];
  1345.  
  1346.     status();
  1347.     output_chr(FLUSH);
  1348.  
  1349.     end = read_str(inp, &history);
  1350.  
  1351.     lp = inp + 1;
  1352.     outp = out + 2;
  1353.     wc = 0;
  1354.  
  1355.     for(;;)
  1356.     {
  1357.         cp = src_word;
  1358.         ws = lp;
  1359.         while (lp < end)
  1360.         {
  1361.             if (p = wordend(c = *lp++))
  1362.                 break;
  1363.             else
  1364.                 if (cp < src_word + 6)
  1365.                     *cp++ = c;
  1366.         }
  1367.  
  1368.         if (lp < end)
  1369.         {
  1370.             if (cp != src_word)
  1371.                 lp--;
  1372.             else if (p < my_terms)
  1373.                 *cp++ = c;
  1374.             else
  1375.                 continue;
  1376.         }
  1377.         else
  1378.         {
  1379.             if (src_word == cp)
  1380.                 break;
  1381.         }
  1382.  
  1383.         if (++wc >= out[0])
  1384.         {
  1385.             output_chr('\n');
  1386.             output_str("too many words for internal buffer\n");
  1387.             out[1] = 0;
  1388.             return;
  1389.         }
  1390.  
  1391.         outp[2] = (char)(lp - ws);
  1392.         outp[3] = (char)(ws - inp);
  1393.         *cp = '\0';
  1394.         encode(dst_word, src_word);
  1395.         word_put(outp, findword(dst_word));
  1396.         outp += 4;
  1397.     }
  1398.     out[1] = wc;
  1399.  
  1400.     if (word_get(main_h->reserved5) & 1)
  1401.     {
  1402.         for (p = inp; *++p; )
  1403.             putc_dev(*p, printer);
  1404.         putc_dev('\n', printer);
  1405.     }
  1406. }
  1407.  
  1408. void print_char(d0)
  1409. WORD d0;
  1410. {
  1411. #ifdef TRACE
  1412.     printf("{'%lc'} ",d0);
  1413. #endif
  1414.     output_chr(d0);
  1415. }
  1416.  
  1417. void write_num(d0)
  1418. WORD d0;
  1419. {
  1420.     char buf[16];
  1421.     register char *p;
  1422.     int flag;
  1423.  
  1424.     flag = 0;
  1425.     if (d0 < 0)
  1426.     {
  1427.         flag = 1;
  1428.         d0 = -d0;
  1429.     }
  1430.  
  1431.     p = buf + 15;
  1432.     *p = '\0';
  1433.     do
  1434.         *--p = d0 % 10 + '0';
  1435.     while(d0 /= 10);
  1436.  
  1437.     if (flag)
  1438.         *--p = '-';
  1439.  
  1440. #ifdef TRACE
  1441.     printf("{%ls} ",p);
  1442. #endif
  1443.     output_str(p);
  1444. }
  1445.  
  1446. void rnd(d0)
  1447. WORD d0;
  1448. {
  1449.     extern long zrandom();
  1450. /*
  1451.     static UWORD rnd0 = 0xffff, rnd1 = 0;
  1452.     register long d1;
  1453.  
  1454.     if (rnd0 == 0xffff)
  1455.     {
  1456.         d1 = Random();
  1457.         rnd0 = d1 >> 16;
  1458.         rnd1 = d1;
  1459.     }
  1460.  
  1461.     d1 = rnd0;
  1462.     d1 |= (rnd0 = rnd1) << 16;
  1463.     d1 >>= 1;
  1464.     d1 = (rnd1 ^= d1);
  1465.     d1 &= 0x7fff;
  1466.     putsomewhere(((UWORD)d1 % d0) + 1);
  1467. */
  1468.     putsomewhere((((UWORD)zrandom() & (UWORD)0x7fff) % d0) + 1);
  1469. }
  1470.  
  1471. void push(d0)
  1472. WORD d0;
  1473. {
  1474.     *(--sp) = d0;
  1475. }
  1476.  
  1477. void pop(d0)
  1478. WORD d0;
  1479. {
  1480.     putvarorsp(d0, *(sp++));
  1481. }
  1482.  
  1483. void setstatuslen(d0)
  1484. WORD d0;
  1485. {
  1486.     status_len = d0;
  1487. }
  1488.  
  1489. void gotopos(d0)
  1490. WORD d0;
  1491. {
  1492.     static int x,y;
  1493.  
  1494.     if (d0 == 0)
  1495.     {
  1496.         if (in_status)
  1497.             gotoXY(x,y);
  1498.  
  1499.         in_status = 0;
  1500.     }
  1501.     else if(d0 == 1)
  1502.     {
  1503.         if (!in_status)
  1504.             storeXY(&x, &y);
  1505.  
  1506.         in_status = 1;
  1507.         gotoXY(0,1);
  1508.     }
  1509. }
  1510.  
  1511. /************************************************************************/
  1512. /*            main interpreter loop                */
  1513.  
  1514. void (*class0[])() = {
  1515.     ret_1,            /* op 0xb0    */
  1516.     ret_0,            /* op 0xb1    */
  1517.     print_im,            /* op 0xb2    */
  1518.     printcr_im,            /* op 0xb3    */
  1519.     nop,            /* op 0xb4    */
  1520.     save_g,            /* op 0xb5    */
  1521.     restore_g,        /* op 0xb6    */
  1522.     restart_g,        /* op 0xb7    */
  1523.     ret_sp,            /* op 0xb8    */
  1524.     inc_sp,            /* op 0xb9    */
  1525.     halt,            /* op 0xba    */
  1526.     newline,        /* op 0xbb    */
  1527.     status,            /* op 0xbc    */
  1528.     verify,            /* op 0xbd    */
  1529.     illegal,        /* op 0xbe    */
  1530.     illegal            /* op 0xbf    */
  1531. };
  1532.  
  1533. char *class0name[] = {
  1534.     "ret_1",            /* op 0xb0    */
  1535.     "ret_0",            /* op 0xb1    */
  1536.     "print_im",            /* op 0xb2    */
  1537.     "printcr_im",            /* op 0xb3    */
  1538.     "nop",            /* op 0xb4    */
  1539.     "save_g",            /* op 0xb5    */
  1540.     "restore_g",        /* op 0xb6    */
  1541.     "restart_g",        /* op 0xb7    */
  1542.     "ret_sp",            /* op 0xb8    */
  1543.     "inc_sp",            /* op 0xb9    */
  1544.     "halt",            /* op 0xba    */
  1545.     "newline",        /* op 0xbb    */
  1546.     "status",            /* op 0xbc    */
  1547.     "verify",            /* op 0xbd    */
  1548.     "illegal",        /* op 0xbe    */
  1549.     "illegal"            /* op 0xbf    */
  1550. };
  1551.  
  1552. void (*class1[])() = {
  1553.     bne,
  1554.     nextinv,
  1555.     firstinv,
  1556.     environment,
  1557.     l11a7e,
  1558.     incr,
  1559.     decr,
  1560.     print_near,
  1561.     illegal,
  1562.     destructobj,
  1563.     objshort,
  1564.     ret,
  1565.     bra,
  1566.     print_far,
  1567.     mov,
  1568.     not
  1569. };
  1570.  
  1571. char *class1name[] = {
  1572.     "bne",
  1573.     "nextinv",
  1574.     "firstinv",
  1575.     "environment",
  1576.     "l11a7e",
  1577.     "inc",
  1578.     "dec",
  1579.     "print_near",
  1580.     "illegal",
  1581.     "destructobj",
  1582.     "objshort",
  1583.     "ret",
  1584.     "bra",
  1585.     "print_far",
  1586.     "mov",
  1587.     "not"
  1588. };
  1589.  
  1590. struct {
  1591.     void (*func)();
  1592.     UBYTE flag;
  1593.     } class2[] = {
  1594.         { illegal,    1 },        /* 00 */
  1595.         { bifnotoneof,    0 },        /* 01 */
  1596.         { cbge,        1 },        /* 02 */
  1597.         { cble,        1 },        /* 03 */
  1598.         { dcbge,    1 },        /* 04 */
  1599.         { icble,    1 },        /* 05 */
  1600.         { bnotcontent,    1 },        /* 06 */
  1601.         { bifthen,    1 },        /* 07 */
  1602.         { or,        1 },        /* 08 */
  1603.         { and,        1 },        /* 09 */
  1604.         { tstbit_jz,    1 },        /* 0a */
  1605.         { setbit,    1 },        /* 0b */
  1606.         { clrbit,    1 },        /* 0c */
  1607.         { store,    1 },        /* 0d */
  1608.         { moveobj,    1 },        /* 0e */
  1609.         { getarrayw,    1 },        /* 0f */
  1610.         { getarrayb,    1 },        /* 10 */
  1611.         { querypropn,    1 },        /* 11 */
  1612.         { getpropnaddr,    1 },        /* 12 */
  1613.         { nextpropn,    1 },        /* 13 */
  1614.         { add,        1 },        /* 14 */
  1615.         { sub,        1 },        /* 15 */
  1616.         { mul,        1 },        /* 16 */
  1617.         { div,        1 },        /* 17 */
  1618.         { mod,        1 },        /* 18 */
  1619.         { illegal,    1 },        /* 19 */
  1620.         { illegal,    1 },        /* 1a */
  1621.         { illegal,    1 },        /* 1b */
  1622.         { illegal,    1 },        /* 1c */
  1623.         { illegal,    1 },        /* 1d */
  1624.         { illegal,    1 },        /* 1e */
  1625.         { illegal,    1 },        /* 1f */
  1626.         { call,    0 },            /* 20 */
  1627.         { putarrayw,    1 },        /* 21 */
  1628.         { putarrayb,    1 },        /* 22 */
  1629.         { setpropn,    1 },        /* 23 */
  1630.         { input,    0 },        /* 24 */
  1631.         { print_char,    1 },        /* 25 */
  1632.         { write_num,    1 },        /* 26 */
  1633.         { rnd,        1 },        /* 27 */
  1634.         { push,    1 },        /* 28 */
  1635.         { pop,    1 },        /* 29 */
  1636.         { setstatuslen,    1 },        /* 2a */
  1637.         { gotopos,    1 },        /* 2b */
  1638.         { illegal,    1 },        /* 2c */
  1639.         { illegal,    1 },        /* 2d */
  1640.         { illegal,    1 },        /* 2e */
  1641.         { illegal,    1 },        /* 2f */
  1642.         { illegal,    1 },        /* 30 */
  1643.         { illegal,    1 },        /* 31 */
  1644.         { illegal,    1 },        /* 32 */
  1645.         { illegal,    1 },        /* 33 */
  1646.         { illegal,    1 },        /* 34 */
  1647. #if 0
  1648.         { illegal,    1 },        /* 35 */
  1649. #else
  1650.         { sound,    1 },        /* 35 */
  1651. #endif
  1652.         { illegal,    1 },        /* 36 */
  1653.         { illegal,    1 },        /* 37 */
  1654.         { illegal,    1 },        /* 38 */
  1655.         { illegal,    1 },        /* 39 */
  1656.         { illegal,    1 },        /* 3a */
  1657.         { illegal,    1 },        /* 3b */
  1658.         { illegal,    1 },        /* 3c */
  1659.         { illegal,    1 },        /* 3d */
  1660.         { illegal,    1 },        /* 3e */
  1661.         { illegal,    1 }        /* 3f */
  1662. };
  1663.  
  1664. char *class2name[] = {
  1665.     "illegal",        /* 00 */
  1666.     "bifnotoneof",        /* 01 */
  1667.     "cbge",        /* 02 */
  1668.     "cble",        /* 03 */
  1669.     "dcbge",        /* 04 */
  1670.     "icble",        /* 05 */
  1671.     "bnotcontent",        /* 06 */
  1672.     "bifthen",        /* 07 */
  1673.     "or",        /* 08 */
  1674.     "and",        /* 09 */
  1675.     "tstbit_jz",        /* 0a */
  1676.     "setbit",        /* 0b */
  1677.     "clrbit",        /* 0c */
  1678.     "store",        /* 0d */
  1679.     "moveobj",        /* 0e */
  1680.     "getarrayw",        /* 0f */
  1681.     "getarrayb",        /* 10 */
  1682.     "querypropn",        /* 11 */
  1683.     "getpropnaddr",        /* 12 */
  1684.     "nextpropn",        /* 13 */
  1685.     "add",        /* 14 */
  1686.     "sub",        /* 15 */
  1687.     "mul",        /* 16 */
  1688.     "div",        /* 17 */
  1689.     "mod",        /* 18 */
  1690.     "illegal",        /* 19 */
  1691.     "illegal",        /* 1a */
  1692.     "illegal",        /* 1b */
  1693.     "illegal",        /* 1c */
  1694.     "illegal",        /* 1d */
  1695.     "illegal",        /* 1e */
  1696.     "illegal",        /* 1f */
  1697.     "call",            /* 20 */
  1698.     "putarrayw",        /* 21 */
  1699.     "putarrayb",        /* 22 */
  1700.     "setpropn",        /* 23 */
  1701.     "input",        /* 24 */
  1702.     "print_char",        /* 25 */
  1703.     "write_num",        /* 26 */
  1704.     "rnd",        /* 27 */
  1705.     "push",        /* 28 */
  1706.     "pop",        /* 29 */
  1707.     "setstatuslen",        /* 2a */
  1708.     "gotopos",        /* 2b */
  1709.     "illegal",        /* 2c */
  1710.     "illegal",        /* 2d */
  1711.     "illegal",        /* 2e */
  1712.     "illegal",        /* 2f */
  1713.     "illegal",        /* 30 */
  1714.     "illegal",        /* 31 */
  1715.     "illegal",        /* 32 */
  1716.     "illegal",        /* 33 */
  1717.     "illegal",        /* 34 */
  1718.     "illegal",        /* 35 */
  1719.     "illegal",        /* 36 */
  1720.     "illegal",        /* 37 */
  1721.     "illegal",        /* 38 */
  1722.     "illegal",        /* 39 */
  1723.     "illegal",        /* 3a */
  1724.     "illegal",        /* 3b */
  1725.     "illegal",        /* 3c */
  1726.     "illegal",        /* 3d */
  1727.     "illegal",        /* 3e */
  1728.     "illegal"        /* 3f */
  1729. };
  1730.  
  1731. int oc;
  1732. int o1;
  1733.  
  1734. void run()
  1735. {
  1736.     register UWORD d0, d1, d2, d3, d4;
  1737.     register UWORD *argp, *bp;
  1738.     UWORD args[6];
  1739.     UWORD bits[4];
  1740.  
  1741.     argp = args;
  1742.     for(;;)
  1743.     {
  1744. #ifdef DEBUG
  1745.         ops[ops_ix].c_pc.offset = pc.offset;
  1746.         ops[ops_ix].c_pc.segment = pc.segment;
  1747.         ops[ops_ix].c_sp = sp - stack;
  1748.         ops[ops_ix].c_fp = framep - stack;
  1749.         ops[ops_ix].c_op = d0 = fetchb_op();
  1750.  
  1751. #ifdef TRACE
  1752.         printf("%02lx:%03lx:%05lx:%02lx ", ops[ops_ix].c_fp, ops[ops_ix].c_sp,
  1753.         (long)ops[ops_ix].c_pc.offset|((long)ops[ops_ix].c_pc.segment<<9),
  1754.         ops[ops_ix].c_op);
  1755. #endif
  1756.  
  1757.         ops_ix = (ops_ix + 1) & 0xff;
  1758. #else
  1759.         d0 = fetchb_op();
  1760. #endif
  1761.         if (d0 < 0x80)
  1762.         {
  1763. #ifdef TRACE
  1764.             printf("%-16s ",class2name[d0 & 0x1f]);
  1765. #endif
  1766.  
  1767.             d1 = getanyop((d0 & 0x40)?2:1);
  1768.  
  1769. #ifdef TRACE
  1770.             printf("%ld:%04lx ",(d0 & 0x40)?2:1, d1);
  1771. #endif
  1772.  
  1773.             d2 = getanyop((d0 & 0x20)?2:1);
  1774. #ifdef TRACE
  1775.             printf("%ld:%04lx ",(d0 & 0x20)?2:1, d2);
  1776. #endif
  1777.  
  1778.             if (class2[d0 & 0x1f].flag)
  1779.             {
  1780. /*                if(class2[d0 & 0x1f].func == illegal)*/
  1781. /*                    DPrintf("\n1) Class2 %ld Illegal!\a\n",d0 & 0x1f);*/
  1782.  
  1783.                 (*class2[d0 & 0x1f].func)(d1, d2);
  1784.             }
  1785.             else
  1786.             {
  1787.                 argp[0] = 2;
  1788.                 argp[1] = d1;
  1789.                 argp[2] = d2;
  1790.  
  1791. /*                if(class2[d0 & 0x1f].func == illegal)*/
  1792. /*                    DPrintf("\n2) Class2 %ld Illegal!\a\n",d0 & 0x1f);*/
  1793.  
  1794.                 (*class2[d0 & 0x1f].func)(argp);
  1795.             }
  1796.         }
  1797.         else if (d0 < 0xb0)
  1798.         {
  1799. #ifdef TRACE
  1800.             printf("%-16s ",class1name[d0 & 0x0f]);
  1801. #endif
  1802.             d1 = getanyop((d0 >> 4) & 0x03);
  1803. #ifdef TRACE
  1804.             printf("%ld:%04lx ", (d0>>4)&0x03, d1);
  1805. #endif
  1806. /*            if(class1[d0 & 0x0f] == illegal)*/
  1807. /*                DPrintf("\n3) Class1 %ld Illegal!\a\n",d0 & 0x0f);*/
  1808.  
  1809.             (*class1[d0 & 0x0f])(d1);
  1810.         }
  1811.         else if (d0 < 0xc0)
  1812.         {
  1813. #ifdef TRACE
  1814.             printf("%-16s ",class0name[d0 & 0x0f]);
  1815. #endif
  1816. /*            if(class0[d0 & 0x0f] == illegal)*/
  1817. /*                DPrintf("\n4) Class0 %ld Illegal!\a\n",d0 & 0x0f);*/
  1818.  
  1819.             (*class0[d0 & 0x0f])();
  1820.         }
  1821.         else
  1822.         {
  1823.             d2 = d0;
  1824.             bp = &bits[4];
  1825.             d0 = fetchb_op();
  1826.             *(--bp) = d0;
  1827.             *(--bp) = (d0 >>= 2);
  1828.             *(--bp) = (d0 >>= 2);
  1829.             *(--bp) = (d0 >>= 2);
  1830. #ifdef TRACE
  1831.             printf("%-16s ",class2name[d2 & 0x3f]);
  1832. #endif
  1833.             for (d4 = 0, d3 = 4; d3; d3--)
  1834.             {
  1835. #ifdef TRACE
  1836.                 printf("%ld:", *bp & 3);
  1837. #endif
  1838.                 if ((d0 = *(bp++) & 3) == 3)
  1839.                     break;
  1840.                 argp[++d4] = getanyop(d0);
  1841. #ifdef TRACE
  1842.                 printf("%04lx ",argp[d4]);
  1843. #endif
  1844.             }
  1845.             argp[0] = d4;
  1846.  
  1847. /*            if(class2[d2 & 0x3f].func == illegal)*/
  1848. /*                DPrintf("\n5) Class2 %ld Illegal!\a\n",d2 & 0x3f);*/
  1849.  
  1850.             if (class2[d2 & 0x3f].flag)
  1851.                 (*class2[d2 & 0x3f].func)
  1852.                     (argp[1],argp[2],argp[3],argp[4]);
  1853.             else
  1854.                 (*class2[d2 & 0x3f].func)(argp);
  1855.         }
  1856. #ifdef TRACE
  1857.         printf("\n");
  1858. #endif
  1859.     }
  1860. }
  1861.  
  1862. /************************************************************************/
  1863. /*                initializiation                */
  1864.  
  1865. void
  1866. main(argc,argv)
  1867. int argc; char **argv;
  1868. {
  1869.     struct header h;
  1870.     register UBYTE *p, *q, *r;
  1871.     register int i;
  1872.  
  1873.     char space[128];
  1874.     extern int optind;
  1875.     extern char *optarg;
  1876.  
  1877.     int c, rflag;
  1878.     char *restore_name;
  1879.     char *strchr(), *strrchr();
  1880.  
  1881. #ifndef AMIGA
  1882.     char *usage;
  1883. # if defined(OSK)
  1884.     usage = "\15\12Usage:\tzmachine [ -p protocolfile ] [ -w protocol linewith ]\
  1885. \15\12\t[ -s storyfile ] [ -r restorefile ] [ <storyfile>.data ]\
  1886. \15\12\t[ <restorefile>.save ]\15\12";
  1887. # else
  1888.     usage = "\r\nUsage:\tzmachine [ -p protocolfile ] [ -w protocol linewith ]\
  1889. \r\n\t[ -s storyfile ] [ -r restorefile ] [ <storyfile>.data ]\
  1890. \r\n\t[ <restorefile>.save ]\r\n";
  1891. # endif
  1892. #endif    /* AMIGA */
  1893.  
  1894.     story_name = restore_name = NULL;
  1895.  
  1896.     rflag = 0;
  1897.  
  1898. #ifdef AMIGA
  1899.     if(DOSBase -> dl_lib . lib_Version < 37)
  1900.         exit(20);
  1901.  
  1902.     if (argc == 0)
  1903.     {
  1904.         extern BYTE CustomScreen;
  1905.  
  1906.         wbtocli(&argc, &argv);
  1907.  
  1908.         while ((c = getopt(argc, argv, "s:p:r:w:k:l:c")) != EOF)
  1909.         {
  1910.             switch(c)
  1911.             {
  1912.                 case 'k':
  1913.                     TwoColours[0] = ahtoi(optarg);
  1914.                     break;
  1915.  
  1916.                 case 'l':
  1917.                     TwoColours[1] = ahtoi(optarg);
  1918.                     break;
  1919.  
  1920.                 case 'c':
  1921.                     CustomScreen = TRUE;
  1922.                     break;
  1923.  
  1924.                 case 's':
  1925.                     story_name = optarg;
  1926.                     break;
  1927.  
  1928.                 case 'p':
  1929.                     strcpy(print_name,optarg);
  1930.                     break;
  1931.  
  1932.                 case 'r':
  1933.                     restore_name = optarg;
  1934.                     rflag++;
  1935.                     break;
  1936.  
  1937.                 case 'w':
  1938.                     if (!(printer_width = atoi(optarg)))
  1939.                         printer_width = 80;
  1940.  
  1941.                     break;
  1942.             }
  1943.         }
  1944.     }
  1945.     else
  1946.     {
  1947.         UBYTE **ArgArray;
  1948.  
  1949.         StdOut = Output();
  1950.  
  1951.         if(ArgArray = (UBYTE **)AllocVec(sizeof(UBYTE *) * (ARGCOUNT),MEMF_ANY | MEMF_CLEAR))
  1952.         {
  1953.             struct RDArgs *ArgsPtr;
  1954.  
  1955.             if(ArgsPtr = (struct RDArgs *)AllocDosObjectTags(DOS_RDARGS,TAG_DONE))
  1956.             {
  1957.                 if(ProgramName = (UBYTE *)malloc(400))
  1958.                 {
  1959.                     UBYTE Buffer[400];
  1960.  
  1961.                     if(!GetProgramName(Buffer,400))
  1962.                     {
  1963.                         free(ProgramName);
  1964.  
  1965.                         ProgramName = NULL;
  1966.                     }
  1967.                     else
  1968.                     {
  1969.                         strcpy((char *)ProgramName,(char *)FilePart(Buffer));
  1970.  
  1971.                         ArgsPtr -> RDA_ExtHelp = &ProgramName[40];
  1972.                     }
  1973.                 }
  1974.  
  1975.                 if(!ProgramName)
  1976.                     ArgsPtr -> RDA_ExtHelp = (UBYTE *)"\nUsage: ZorkMachine [Protocol <Protocol file>, Default = PRT:]\n\
  1977.                    [Width <Protocol file line width>, Default = 80 characters]\n\
  1978.                    [Story <Story file>, Default = Story.Data]\n\
  1979.                    [Restore <Saved game file>]\n\
  1980.                    [Customscreen]\n\
  1981.                    [Colour0 <Background colour>] [Colour1 <Text colour>]\n";
  1982.                 else
  1983.                     sprintf((char *)ArgsPtr -> RDA_ExtHelp,"\nUsage: %s [Protocol <Protocol file>, Default = PRT:]\33[B\33[42D\
  1984. [Width <Protocol file line width>, Default = 80 characters]\33[B\33[59D\
  1985. [Story <Story file>, Default = Story.Data]\33[B\33[42D\
  1986. [Restore <Saved game file>]\33[B\33[27D\
  1987. [Customscreen]\33[B\33[14D\
  1988. [Colour0 <Background colour>] [Colour1 <Text colour>]\n",ProgramName);
  1989.  
  1990.                 if(ArgsPtr = ReadArgs((UBYTE *)"P=PROTOCOL/K,W=WIDTH/K/N,S=STORY/K,R=RESTORE/K,C=CUSTOMSCREEN/S,C0=COLOUR0/K,C1=COLOUR1/K",(LONG *)ArgArray,ArgsPtr))
  1991.                 {
  1992.                     if(ArgArray[ARG_COLOUR0])
  1993.                         TwoColours[0] = ahtoi(ArgArray[ARG_COLOUR0]);
  1994.  
  1995.                     if(ArgArray[ARG_COLOUR1])
  1996.                         TwoColours[1] = ahtoi(ArgArray[ARG_COLOUR1]);
  1997.  
  1998.                     if(ArgArray[ARG_PROTOCOL])
  1999.                         strcpy(print_name,(char *)ArgArray[ARG_PROTOCOL]);
  2000.  
  2001.                     if(ArgArray[ARG_WIDTH])
  2002.                     {
  2003.                         printer_width = *(LONG *)ArgArray[ARG_WIDTH];
  2004.  
  2005.                         if(printer_width < 1)
  2006.                             printer_width = 80;
  2007.                     }
  2008.  
  2009.                     if(ArgArray[ARG_STORY])
  2010.                     {
  2011.                         if(story_name = malloc(strlen((char *)ArgArray[ARG_STORY]) + 1))
  2012.                             strcpy(story_name,(char *)ArgArray[ARG_STORY]);
  2013.                     }
  2014.  
  2015.                     if(ArgArray[ARG_RESTORE])
  2016.                     {
  2017.                         if(restore_name = malloc(strlen((char *)ArgArray[ARG_RESTORE]) + 1))
  2018.                             strcpy(restore_name,(char *)ArgArray[ARG_RESTORE]);
  2019.                     }
  2020.  
  2021.                     if(ArgArray[ARG_CUSTOMSCREEN])
  2022.                     {
  2023.                         extern BYTE CustomScreen;
  2024.  
  2025.                         CustomScreen = TRUE;
  2026.                     }
  2027.  
  2028.                     FreeArgs(ArgsPtr);
  2029.                 }
  2030.                 else
  2031.                 {
  2032.                     PrintFault(IoErr(),(UBYTE *)"ZorkMachine");
  2033.  
  2034.                     FreeDosObject(DOS_RDARGS,ArgsPtr);
  2035.  
  2036.                     FreeVec(ArgArray);
  2037.  
  2038.                     exit(RETURN_ERROR);
  2039.                 }
  2040.  
  2041.                 FreeDosObject(DOS_RDARGS,ArgsPtr);
  2042.             }
  2043.  
  2044.             FreeVec(ArgArray);
  2045.         }
  2046.     }
  2047.  
  2048. #else
  2049.     while ((c = getopt(argc, argv, "s:p:r:w:")) != EOF)
  2050.     {
  2051.         switch(c)
  2052.         {
  2053.             case 's':
  2054.                 story_name = optarg;
  2055.                 break;
  2056.  
  2057.             case 'p':
  2058.                 strcpy(print_name,optarg);
  2059.                 break;
  2060.  
  2061.             case 'r':
  2062.                 restore_name = optarg;
  2063.                 rflag++;
  2064.                 break;
  2065.  
  2066.             case 'w':
  2067.                 if (!(printer_width = atoi(optarg)))
  2068.                     printer_width = 80;
  2069.                 break;
  2070.  
  2071.             default:
  2072.                 exit(userexit(1));
  2073.         }
  2074.     }
  2075.  
  2076.     while (optind < argc)
  2077.     {
  2078.         char *tmp;
  2079.  
  2080.         if ((tmp = strrchr(argv[optind],'.')) &&
  2081.             (!stricmp(tmp,".data") || !stricmp(tmp, ".dat")))
  2082.             story_name = argv[optind];
  2083.         else if (tmp && (!stricmp(tmp, ".Save") || !stricmp(tmp, ".sav")))
  2084.         {
  2085.             rflag++;
  2086.             restore_name = argv[optind];
  2087.         }
  2088.         else
  2089.         {
  2090.             fatal("Unknown filetype", argv[optind]);
  2091.         }
  2092.         optind++;
  2093.     }
  2094. #endif    /* AMIGA */
  2095.  
  2096.     if (!story_name && restore_name && strchr(restore_name,'.'))
  2097.     {
  2098.         strcpy(space, restore_name);
  2099.         strcpy(strchr(space, '.'), ".data");
  2100.  
  2101.         if (access(space,0))
  2102.         {
  2103.             strcpy(strchr(space, '.'), ".dat");
  2104.  
  2105.             if (access(space,0))
  2106.                 story_name = "Story.Data";
  2107.         }
  2108.         else
  2109.             story_name = space;
  2110.     }
  2111.  
  2112.     if (!story_name)
  2113.         story_name = "Story.Data";
  2114.  
  2115.     if (open_story())
  2116.         fatal("Can't open", story_name);
  2117.  
  2118.     read_header(&h);
  2119.  
  2120.     if (h.zmachine != 3)
  2121.         fatal("Wrong Z-machine version", story_name);
  2122.  
  2123.     mmu_init(&h);
  2124.  
  2125.     read_story(0, main_l, main_p);
  2126.  
  2127.     in_status = 0;
  2128.  
  2129.     release = word_get(h.release);
  2130. #ifdef TRACE
  2131.     printf("Release: %ld\n", release);
  2132. #endif
  2133.  
  2134.     status_type = (h.flags & 2) >> 1;
  2135. #ifdef TRACE
  2136.     printf("Flags: %08lx\n", h.flags);
  2137. #endif
  2138.  
  2139.     ff0 = main_p + word_get(h.reserved2);
  2140.     fec = main_p + word_get(h.reserved3);
  2141.     short_cuts = main_p + word_get(h.short_cuts);
  2142.     save_len = btop((long)word_get(h.save_len));
  2143.     if (!(stack = (UWORD *)malloc(0x100 * sizeof(WORD))))
  2144.         no_mem_error();
  2145.  
  2146.     printer = init_dev(prot_write, prot_crlf, printer_width, 0, 0);
  2147.  
  2148.     if (!(terms = (char *)malloc(0x40)))
  2149.         no_mem_error();
  2150.  
  2151.     q = main_p + word_get(h.vocabulary);
  2152.     for(p = (UBYTE *)terms, i = *(q++); i; i--)
  2153.         *p++ = *q++;        /* copy terminators    */
  2154.  
  2155.     my_terms = (char *)p;
  2156.     for(r = (UBYTE *)" \011\015.,?"; *p++ = *r++;)
  2157.         ;            /* copy my terminators    */
  2158.  
  2159.     word_len = *q++;        /* word-len        */
  2160.     word_num = word_get(q);        /* number of words    */
  2161.     q += 2;
  2162.  
  2163.     first_word = q;            /* start of words    */
  2164.     last_word = (word_num - 1) * word_len + first_word;
  2165.                     /* end of words        */
  2166.  
  2167.     if (setjmp(restart_buf))
  2168.     {
  2169.         rflag = 0;
  2170.         i = word_get(main_h->reserved5);
  2171.         read_story(0, save_len, main_p);
  2172.         word_put(main_h->reserved5, i);
  2173.     }
  2174.  
  2175.     printer->bp = printer->buffer;
  2176.     printer->count = 0;
  2177.     main_h->flags |= 32;
  2178.  
  2179.     status_len = 1;
  2180.     init_con();
  2181.     if (!rflag)
  2182.     {
  2183.         sp = &stack[0x100];
  2184.         framep = sp - 1;
  2185.         baddr_to_vaddr(&pc, word_get(h.initial_pc));
  2186.         load_code();
  2187.     }
  2188.     else
  2189.     {
  2190.         if (restore_gf(restore_name))
  2191.             jump(1);
  2192.         else
  2193.             fatal("Cannot load restore file", restore_name);
  2194.     }
  2195.     run();
  2196. }
  2197.